package com.manli.api.base.aop;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.manli.api.base.annotation.Permissions;
import com.manli.api.enums.AuthEnums;
import com.manli.api.enums.ResultEnums;
import com.manli.api.pojo.SessionInfo;
import com.manli.api.util.IPUtils;
import com.manli.api.util.JwtUtils;
import com.manli.api.util.ResultUtil;
import com.manli.api.util.SessionInfoUtils;

import io.jsonwebtoken.Claims;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.NamedThreadLocal;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;


/**
 * 拦截所有.do 根据WebAppConfig
 */
public class AuthenticationInterceptor implements HandlerInterceptor   {

	
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	private NamedThreadLocal<Long>  startTimeThreadLocal = new NamedThreadLocal<Long>("StopWatch-StartTime");  

	@Autowired
	SessionInfoUtils sessionInfoUtils;
	
	
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object obj, Exception ex)
			throws Exception {
		//2、结束时间
	    long endTime = System.currentTimeMillis();
		//得到线程绑定的局部变量（开始时间）
        long beginTime = startTimeThreadLocal.get();
		//3、消耗的时间
        long consumeTime = endTime - beginTime;
        if(consumeTime > 500) {
        	//此处认为处理时间超过500毫秒的请求为慢请求
            logger.error( String.format("%s consume %d millis", request.getRequestURI(), consumeTime));
        }       
	}




	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object obj, ModelAndView model)
			throws Exception {
	}


	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

		//1、开始时间
        long beginTime = System.currentTimeMillis();
		//线程绑定变量（该数据只有当前请求的线程可见）
        startTimeThreadLocal.set(beginTime);
		HandlerMethod method = null;
		if (handler instanceof HandlerMethod) {
			//说明是方法
			method = (HandlerMethod)handler;
		} else {
			//说明是其他静态资源等 直接不进入
			sendResponseErrorJsonMsg(response, ResultEnums.NO_METHO_URL);
			return false;
		}
		//必须知道是谁 session 或 jwt token
		SessionInfo sessionInfo = getSessionInfoByAuth(request);
		//检查是否有权限
		return authPermissions(method,sessionInfo,request,response);
	}



	/**
	 * 集成session 和 jwt token 获取用户信息
	 * session 
	 * 		key sessionInfo
	 * 		过期时间 在启动类注解上上已经设置
	 * jwt token
	 * 		key sessionInfo:userId+
	 * @param request
	 * @return
	 */
	public SessionInfo getSessionInfoByAuth(HttpServletRequest request) {
		return sessionInfoUtils.getSessionInfoByAuth(request);
	}
	/**
	 * 校验是否有权限
	 * @throws IOException 
	 */
	public boolean authPermissions(HandlerMethod method,SessionInfo sessionInfo,HttpServletRequest request,HttpServletResponse response) throws IOException {
		//校验权限
		String methodUrl = request.getServletPath();
		String packageName = method.getBeanType().getPackage().getName();

	    if(method.getMethod().isAnnotationPresent(Permissions.class)){
        	Permissions needVerify = method.getMethod().getAnnotation(Permissions.class);
        	if (needVerify.typeOfAccess() == Permissions.METHOD_LOGIN_PERMISSONS) {
        		//需要登陆并且有权限
        		if(sessionInfo == null) {
        			sendResponseErrorJsonMsg(response, ResultEnums.NO_LOGIN);
        			return false;
        		}
        		if(JSONObject.toJSONString(sessionInfo.getUserPermissions()).indexOf(methodUrl)>-1) {
        			//有权限
        			return true;
        		}else {
        			//没有权限
        			sendResponseErrorJsonMsg(response, ResultEnums.NO_PERMISSIONS);
        			return false;
        		}
			} else if(needVerify.typeOfAccess() == Permissions.METHOD_LOGIN) {
        		//需要登陆
				if("com.manli.api.controller.wechat".equals(packageName)){
					if(sessionInfo == null) {
						sendResponseErrorJsonMsg(response, ResultEnums.NO_LOGIN);
						return false;
					}
					if (sessionInfo.getWeChatUserInfo() == null){
						sendResponseErrorJsonMsg(response, ResultEnums.NO_LOGIN);
						return false;
					}
				}
				if(sessionInfo == null) {
        			sendResponseErrorJsonMsg(response, ResultEnums.NO_LOGIN);
        			return false;
        		}else {
					return true;
				}
			} else if(needVerify.typeOfAccess() == Permissions.METHOD_OPEN){
        		//开放接口
				return true;
			}else {
				sendResponseErrorJsonMsg(response, ResultEnums.Permissions_NO_TYPEOFACCESSS);
				return false;
			}
        }else{
        	sendResponseErrorJsonMsg(response, ResultEnums.METHOD_NEED_SET_INTERFACE_PERMISSONS);
        	return false;  
        }
	}
	
	/**
	 * 直接response返回json信息给前端 错误信息
	 * @param response
	 * @param enums
	 * @throws IOException
	 */
	public void sendResponseErrorJsonMsg(HttpServletResponse response,ResultEnums enums) throws IOException {
		response.setCharacterEncoding("utf-8");
	    response.setContentType("application/json; charset=utf-8");
	    PrintWriter writer = response.getWriter();
	    writer.write(JSONObject.toJSONString(ResultUtil.error(enums.getCode(), enums.getMsg())));
	    logger.info(enums.getMsg());
	}
	
	/**
	 * 直接response返回json信息给前端 错误信息
	 * @param response
	 * @param enums
	 * @throws IOException
	 */
	public void sendResponseSuccessJsonMsg(HttpServletResponse response,ResultEnums enums) throws IOException {
		response.setCharacterEncoding("utf-8");
	    response.setContentType("application/json; charset=utf-8");
	    PrintWriter writer = response.getWriter();
	    writer.write(JSONObject.toJSONString(ResultUtil.success(enums.getMsg())));
		logger.info(enums.getMsg());
	}
	
	

}
